home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / run123.com / T5DOS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-03-16  |  11.0 KB  |  312 lines

  1. {═══════════════════════════════ T5DOS.PAS ═══════════════════════════════}
  2. { ───────────  Turbo 4.0/5.0 subprocess demonstration program  ────────── }
  3. {                 Copyright (c) 1989  Richard W. Prescott                 }
  4. { This Unit provides routines which are Call & Result compatible with     }
  5. { GetEnv, FSearch, and SwapVectors from the Turbo 5.0 DOS Unit.  They     }
  6. { are used in the main program RUN123.PAS and are provided here for the   }
  7. { benefit of Turbo 4.0 Users and for those interested in seeing how such  }
  8. { routines might be implemented.  These are independent implementations   }
  9. { developed without reference to the run-time source code and without     }
  10. { disassembling Turbo 5.0 object code.                                    }
  11. { Users familiar with EXTERNAL Assembly routines should note that with    }
  12. { TP&Asm you can have multiple Assembly Proc/Functions in the same source }
  13. { file with Smart-Linking on an individual Procedure basis.  This is in   }
  14. { contrast to External OBJ files with multiple Assembly Proc/Functions    }
  15. { which are linked on an All-or-Nothing basis.  Using TP&Asm permits the  }
  16. { development of efficient libraries of Assembly procedures without       }
  17. { littering your system with an infinite number of source and OBJ files.  }
  18. {═════════════════════════════════════════════════════════════════════════}
  19. { This Unit was compiled and assembled using Turbo Pascal Version 4.0     }
  20. { and TP&Asm Version 2 ß.  TP&Asm provides an integrated compile-time     }
  21. { assembler within the Turbo development environment (and the command     }
  22. { line compiler TPC), resulting in an ASSEMBLY Development Environment    }
  23. { which is identical to your PASCAL Development Environment.              }
  24. {                                                                         }
  25. { TP&Asm Version 2.0 will be available from me for $49 plus $3 P&H.  The  }
  26. { current Beta Test Version 2 ß is available now for $39 plus $3 P&H,     }
  27. { with a free upgrade to 2.0 when it becomes available.                   }
  28. {          Please see the README file for further information.            }
  29. {═════════════════════════════════════════════════════════════════════════}
  30.  
  31. Unit T5DOS;
  32.  
  33. interface
  34.  
  35.   TYPE PathStr = STRING[79];
  36.  
  37.   FUNCTION GetEnv(EnvVar: STRING): STRING;
  38.   FUNCTION FSearch(Path: PathStr; DirList: STRING): PathStr;
  39.   PROCEDURE SwapVectors; 
  40.  
  41. implementation
  42.  
  43.  
  44. {════════════════════════════════ GetEnv ═════════════════════════════════}
  45. { Call with the name of an Environment Variable (upper/lower/mixed Case), }
  46. { excluding the "=".  Returns the same string which would be displayed by }
  47. { the DOS "Set" command, beginning with the first Char following the "=". }
  48. {════════════════════════════════ GetEnv ═════════════════════════════════}
  49. FUNCTION GetEnv(EnvVar: STRING): STRING;
  50. BEGIN
  51.   Assembly
  52.  
  53.   ResultStr EQU D[Bp+10]; pointer to function result, determined via EXAMINE
  54.  
  55. ;- 1. Set Env Pointer Es:Di (EnvSeg := MemW[PrefixSeg:$2C];)
  56.   Mov Es,PrefixSeg
  57.   Es Mov Es,[02C]
  58.   Xor Di,Di
  59.   Cld                 ; All String Operations will be FORWARD
  60.  
  61. ;- 2. convert EnvVar to UpCase and set Cx
  62.   Push Ds,Ss
  63.   Pop Ds              ; Point Ds:Si to local copy of EnvVar
  64.   Lea Si,EnvVar
  65.   Xor Ah,Ah
  66.   LodSB
  67.   Xchg Ax,Cx          ; Set counter to Length(EnvVar)
  68.   Mov Dx,Cx           ; save count
  69.   Mov Bx,Si           ; and start offset
  70.   jCXZ ExitEmpty
  71.  L0:
  72.   And B[Si],0DF       ; capitalize
  73.   Inc Si
  74.   Loop L0
  75. ;- set to go with capitalized EnvVar
  76.  
  77. ;- 3. exit if FIRST byte of current Env string is 0
  78.  CheckEnvString:
  79.   Mov Cx,Dx           ; reset count
  80.   Mov Si,Bx           ; and start offset
  81.   Es Cmp B[Di],0
  82.   jZ ExitEmpty
  83.  
  84. ;- 4. Else CmpSB EnvVar with current Env Pointer
  85.   RepE CmpSB
  86.   jNE Scan0
  87.  
  88. ;- 5. Found, check for '='
  89.   Es Cmp B[Di],'='
  90.   jE ExitFound
  91.  
  92. ;- 6. Not found: Scan for b(0) and goto 3.
  93.  Scan0:
  94.   Dec Di              ; back up one
  95.   Mov Cx,07FFF        ; max env length
  96.   Xor Al,Al           ; search for 0 byte
  97.   RepNE ScaSB         ; leaves Di pointing immediately PAST the 0 byte
  98.   jNE ExitEmpty       ; Env Error, report not found
  99.   Jmp CheckEnvString  ; Repeat steps 3-6
  100.  
  101. ;- 7. Found, set result & Exit
  102.  ExitFound:
  103.   Inc Di              ; now Es:Di points to null terminated Env String
  104.   Push Di
  105.   Xor Al,Al
  106.   Mov Cx,255
  107.   RepNE ScaSB         ; leaves Di pointing immediately PAST the 0 byte
  108.   jNE ErrorEmpty      ; Env Error, pop Di and report not found
  109.   Dec Di              ; adjust
  110.   Pop Ax              ; old value of Di
  111.   Sub Di,Ax           ; string length in Di
  112.   Xchg Ax,Di          ; string length in Ax, restore Di
  113.   Cmp Ax,255
  114.   jA ExitEmpty        ; Env Error, report not found
  115.   
  116.   Push Es
  117.   Pop Ds
  118.   Mov Si,Di           ; now Ds:Si points to null terminated Env String
  119.  
  120.   Les Di,ResultStr    ; Load Es:Di with pointer to Function Result
  121.   Mov Cx,Ax
  122.   StoSB               ; store result length
  123.   Rep MovSB           ; move result string
  124.   Jmp Done
  125.  
  126.  ErrorEmpty:
  127.   Pop Di              ; clear pending push
  128.  ExitEmpty:
  129.   Les Di,ResultStr    ; Load Es:Di with pointer to Function Result
  130.   Xor Al,Al
  131.   StoSB               ; store result length = 0
  132.  
  133.  Done: 
  134.   Pop Ds
  135.   END; {Assembly}
  136. END; {FUNCTION GetEnv}
  137.  
  138.  
  139. {════════════════════════════════ FSearch ════════════════════════════════}
  140. { Call with the File or Path name of a file to search for, and a list of  }
  141. { directories to search, separated by semi-colons ";" (ie, in standard    }
  142. { DOS Path format).  Searches current directory first, then searches each }
  143. { directory or drive in DirList.  If a DirList entry consists of a Drive  }
  144. { only (eg "C:"), searches active directory and then root directory of    }
  145. { that drive.  If found, Returns the full path string (directory prefix   }
  146. { plus file Path) used in the successful search.  If not found, Returns   }
  147. { an empty string.  FSearch finds only true files (including read-only,   }
  148. { hidden, and system files), not Volume labels or Sub-directories.        }
  149. {════════════════════════════════ FSearch ════════════════════════════════}
  150. FUNCTION FSearch(Path: PathStr; DirList: STRING): PathStr;
  151. VAR FullPath: STRING;    {- STRING[80] would suffice -}
  152.     TryRoot:  BOOLEAN;
  153. BEGIN
  154.  Assembly
  155.   ResultPath EQU D[Bp+14] ; Ptr to function result
  156. ;- 1. Initialize stuff
  157.   Cld                 ; All String Operations will be FORWARD
  158.   Mov TryRoot,TRUE
  159.   Push Ds,Ss,Ss       ; save Dseg
  160.   Pop Ds,Es           ; and point Ds & Es to Stack
  161.   Lea Si,DirList
  162.   Inc Si
  163.   Push Si             ; save current position within DirList
  164.   Lea Di,FullPath
  165.   Mov Bx,Di           ; Save, points to FullPath length byte
  166.   Inc Di
  167.   Mov Dx,Di           ; Save start of AsciiZ, also used by function $43
  168.  
  169. ;- 2. Append Path to FullPath
  170.  AppendPath:
  171.   Lea Si,Path
  172.   Xor Ax,Ax
  173.   LodSB
  174.   Xchg Cx,Ax
  175.   Mov Ax,Di           ; End of DosPath Prefix
  176.   Add Ax,Cx           ; Plus length of 'Path'
  177.   Sub Ax,Dx           ; Minus start of AsciiZ = length of Full Path
  178.   Cmp Ax,79           ; Max length of a PathStr
  179.   jA NotYetFound      ; IF Above, SKIP Move, go try next DosPath Prefix
  180.   Mov B[Bx],Al        ; Put in FullPath length byte
  181.   Rep MovSB           ; Append Path
  182.   Xor Al,Al
  183.   StoSB               ; Make AsciiZ
  184.  
  185. ;- 3. Get File Attr to test for file existence
  186.   Mov Ax,$4300        ; Note - Ds:Dx is already set, points to the AsciiZ
  187.   Int 21h
  188.   jC NotYetFound      ; Only possible failure is Path/File not found
  189.   Test Cx,0018
  190.   jZ ExitFound        ; Treat VolumeLabels and SubDirs as not found
  191.  
  192. ;- 4. Not yet found - get next DosPath Prefix from DirList
  193.  NotYetFound:
  194.   Xor Ax,Ax
  195.   Lea Si,DirList
  196.   LodSB               ; Load Length
  197.   Pop Si              ; current position in DirList
  198.   Lea Cx,DirList
  199.   Inc Cx              ; start offset of DirList
  200.   Add Cx,Ax           ; Add length of DirList
  201.   Sub Cx,Si           ; Minus current Pos = Characters remaining
  202.   jBE ExitEmpty       ; End of DirList, still not found
  203.   Mov Di,Dx           ; = offset of AsciiZ FullPath to load
  204.  L0:                  ; Get next DosPath Prefix
  205.   LodSB
  206.   Cmp Al,';'
  207.   jE >L1
  208.   StoSB               ; store to FullPath at Es:Di
  209.   Loop L0
  210.   Inc Si              ; Adjust Si in case LAST DosPath Prefix is Drive-Only
  211.  L1:
  212. ;- for drive-only prefix eg 'D:', need to try both 'D:' and 'D:\'
  213.   Cmp B[Di-1],':'
  214.   jNE >L2
  215.   Xor TryRoot,TRUE
  216.  ;- First Pass Toggles to FALSE: 
  217.   jNZ >L2             ; NZ = 2nd Pass; add trailing '\' to try root dir
  218.   Sub Si,3            ; ELSE reset Si for 2nd Pass,
  219.   Push Si             ; Save,
  220.   Jmp AppendPath      ; and try using Drive-Only
  221.  
  222.  L2:
  223. ;- see if trailing '\' must be added
  224.   Push Si             ; Si points PAST the semi-colon to next DosPath Prefix
  225.   Mov Al,'\'
  226.   Cmp B[Di-1],Al
  227.   IF NE StoSB         ; add trailing '\' if nec
  228.   Jmp AppendPath      ; Repeat steps 2-4
  229.  
  230.  ExitEmpty:
  231.   Mov B[Bx],0         ; set zero length, don't need to POP Si
  232.   Jmp PutInResult
  233.  
  234.  ExitFound:
  235.   Pop Si              ; clear pending PUSH
  236.  
  237. ;- 6. put in function result
  238.  PutInResult:
  239.   Lea Si,FullPath
  240.   Les Di,ResultPath
  241.   Xor Ax,Ax
  242.   LodSB
  243.   Mov Cx,Ax           ; set move count
  244.   StoSB               ; mov length byte
  245.   IF NCXZ Rep MovSB   ; and move path string
  246.  
  247.   Pop Ds
  248.  
  249.  END; {Assembly}
  250. END; {FUNCTION FSearch}
  251.  
  252.  
  253. {══════════════════════════════ SwapVectors ══════════════════════════════}
  254. { Turbo 4.0 takes over 5 interrupt vectors: 00h, 02h, 23h, 24h, and 75h.  }
  255. { The original values of these vectors are stored in the System Unit VARs }
  256. { SaveInt00, SavInt02, etc.  This procedure interchanges the saved values }
  257. { with the current values of the interrupt vectors.  SwapVectors should   }
  258. { be called immediately before and after calling the DOS Unit Exec Proc.  }
  259. {══════════════════════════════ SwapVectors ══════════════════════════════}
  260.   Internal SwapV
  261. ;- SwapVectors has no parameters -
  262. ;- Use INTERNAL to eliminate standard Pascal Entry/Exit Code
  263.  
  264.   CODE Segment
  265.  
  266.   SwapVectors PROC FAR
  267.  
  268.     Mov Al,00h
  269.     Mov Si,Offset SAVEINT00
  270.     Call SwapVec
  271.     Mov Al,02h
  272.     Mov Si,Offset SAVEINT02
  273.     Call SwapVec
  274.     Mov Al,23h
  275.     Mov Si,Offset SAVEINT23
  276.     Call SwapVec
  277.     Mov Al,24h
  278.     Mov Si,Offset SAVEINT24
  279.     Call SwapVec
  280.     Mov Al,75h
  281.     Mov Si,Offset SAVEINT75
  282.     Call SwapVec
  283.  
  284.     RET
  285.  
  286.    SwapVec PROC NEAR
  287.    ;- Called with  Al = Intr Number  and  Si = Offset SaveIntXX
  288.  
  289.     Mov Ah,035h    ; Get Interrupt Vector
  290.     Int 21h        ;  .. Sets Es:Bx to Intr Vector
  291.  
  292.    ;- Leave Ds addressing Turbo DSeg for following memory refs
  293.     Mov Cx,[Si+2]  ; Load SaveIntXX into Cx:Dx
  294.     Mov Dx,[Si]    ;  for subsequent Set Vector Call
  295.     Mov [Si+2],Es  ; Store Es:Bx from previous
  296.     Mov [Si],Bx    ;  Get Vector Call into SaveIntXX
  297.  
  298.    ;- Now set Ds for Set Vector Call
  299.     Push Ds
  300.     Mov Ds,Cx
  301.     Mov Ah,025h    ; Set Interrupt Vector
  302.     Int 21h        ;  .. Sets Intr Vector to Ds:Dx
  303.     Pop Ds
  304.     Ret            ; Return from SwapVec
  305.    SwapVec ENDP
  306.  
  307.   SwapVectors ENDP
  308.   CODE ENDS
  309.   END {- Internal SwapV -}
  310.  
  311. END.
  312.